//Business
#pragma once
#include "Bios/Interface.h"



class User;
class Market;
class PendingItem;
class Timeout;
class Dealing;
class Trade;


struct BusinessCommand;

class Business : public IMarketHandler, public IDealingHandler
{
public:
	Business(User& user)
		:m_user(user)
	{
		static int s_id = 0;
		m_id = s_id++;
	}
	virtual ~Business() = 0 {}

	int GetId() const { return m_id; }
	User& GetUser() const { return m_user; }
	ContractIndexSet const& GetContractIndexSet() const { return m_contractIndexSet; }

	void OnInit()
	{
		OnBefore();
		DoOnInit();
		OnAfter();
	}

	void OnTimeout(Timeout const& timeout)
	{
		OnBefore();
		DoOnTimeout(timeout);
		OnAfter();
	}

	void OnCommand(BusinessCommand const& command)
	{
		OnBefore();
		DoOnCommand(command);
		OnAfter();
	}

	void OnExchangeStatus(int exchangeStatus)
	{
		OnBefore();
		DoOnExchangeStatus(exchangeStatus);
		OnAfter();
	}

protected:
	void AddContract(int contract)
	{
		m_contractIndexSet.push_back(contract);
	}

private:
	virtual void OnBefore() {}
	virtual void OnAfter() {}

	virtual void DoOnInit() = 0;
	virtual void DoOnMarket(Market const& market) = 0;
	virtual void DoOnPending(PendingItem const& pendingItem) = 0;
	virtual void DoOnCommand(BusinessCommand const& command) = 0;
	virtual void DoOnTimeout(Timeout const& timeout) = 0;
	virtual void DoOnDealing(Dealing const& dealing) = 0;
	virtual void DoOnTrade(Trade const& trade) = 0;
	virtual void DoOnExchangeStatus(int exchangeStatus) = 0;

private:
	int m_id;
	User& m_user;
	ContractIndexSet m_contractIndexSet;
};


template<class DefiniteBusiness>
class AutoUpdateUIBusiness : public Business 
{
protected:
	class SnapshotNotifier
	{
	public:
		SnapshotNotifier(DefiniteBusiness& business)
			:m_business(business),m_snapshot(business.GetSnapshot())
		{
		}
		~SnapshotNotifier()
		{
			DefiniteBusiness::Snapshot snapshot = m_business.GetSnapshot();
			if (snapshot != m_snapshot)
			{
				m_business.UpdateUI(snapshot);
			}
		}
	private:
		typename DefiniteBusiness& m_business;
		typename DefiniteBusiness::Snapshot m_snapshot;
	};

public:
	AutoUpdateUIBusiness(User& user)
		:Business(user)
	{
	}
};
